package com.apestech.framework.xml.condition.modul;

import com.apestech.formwork.condition.ConditionUtil;
import com.apestech.framework.db.SqlResultSet;
import com.apestech.framework.db.SqlSession;
import com.apestech.framework.db.callback.QueryCallBackHandler;
import com.apestech.framework.json.JSONArray;
import com.apestech.framework.json.JSONObject;
import com.apestech.framework.util.DBPub;
import com.apestech.framework.util.LocalVariable;
import com.apestech.framework.util.callback.SpiltStrCallback;
import com.apestech.framework.xml.plugin.modul.SysCondition;

import java.sql.SQLException;
import java.util.ArrayList;

/**
 * @author hup
 * @create 2019-01-23-9:36
 */
public class Dimension extends ConditionUtil{
    private String id;
    private String name;
    private ArrayList<Field> fields=new ArrayList<Field>();
    private JSONObject fieldmap=new JSONObject();
    private JSONObject fielddir=new JSONObject();
    private SqlSession session;
    private JSONArray flist;
    private String fieldKey;
    private int fieldSize;
    private String fieldKeyId;
    private String fieldKeyName;
    private ArrayList<String> fieldKeyList;
    private SysCondition sysCondition;
    private boolean cache=false;
    private String master;
    private boolean stop=false;
    private boolean ismap=true;
    private String fromTab;

    public Dimension(SqlSession session) throws Exception {
        this.session=session;
        sysCondition= LocalVariable.getConfig().getSysCondition(session);
    }

    public void copyDimension(Dimension dimension) throws Exception {
        this.id=dimension.id;
        this.name=dimension.name;
        this.fields=dimension.fields;
        this.fieldmap=dimension.fieldmap;
        this.session=dimension.session;
        this.flist=dimension.flist;
        this.fieldKey=dimension.fieldKey;
        this.fieldSize=dimension.fieldSize;
        this.fieldKeyId=dimension.fieldKeyId;
        this.fieldKeyName=dimension.fieldKeyName;
        this.fieldKeyList=dimension.fieldKeyList;
        this.sysCondition=dimension.sysCondition;
        this.fielddir=dimension.fielddir;
        this.stop=dimension.stop;
        this.ismap=dimension.ismap;
    }

    public void setDimension(JSONObject map){
        if(map==null) return;
        this.id=map.getString("id");
        this.name=map.getString("name");
        this.fromTab=map.getString("fromTab");
        this.stop="1".equals(map.getString("stop"));
        this.ismap="1".equals(map.getString("ismap"));
    }

    public void setMaster(String master) {
        this.master = master;
    }

    //来源XML
    public void addField(JSONObject map) throws Exception {
        master=map.getString("master");
        fromTab=map.getString("fromTab");
        ismap="1".equals(map.getString("ismap"));
        fieldKey=map.getString("fields");
        if(fieldKey!=null){
            execSplitStr(fieldKey, ",", new SpiltStrCallback() {
                @Override
                public void exec(String fid) throws Exception {
                    addSingleField(fid);
                }
            });
        } else throw new Exception("没有配置字段ID，请通过id或者fields属性补全！");
    }

    //来源数据库
    public void addField(String id, String name, String fields) throws Exception {
        this.id=id;
        this.fieldKey=fields;
        this.fieldKeyName=name;
        if(fieldKey!=null){
            execSplitStr(fieldKey, ",", new SpiltStrCallback() {
                @Override
                public void exec(String fid) throws Exception {
                    addSingleField(fid);
                }
            });
        } else throw new Exception("没有配置字段ID，请通过id或者fields属性补全！");
    }

    private void addSingleField(String id) throws Exception {
        JSONObject map=new JSONObject();
        map.put("id", id);
        addSingleField(id, map);
    }

    private void addSingleField(String id, JSONObject map) throws Exception {
        if(id==null) throw new Exception("没有配置字段ID，请通过id或者fields属性补全！");
        id=id.trim();
        if("".equals(id))  throw new Exception("没有配置字段ID，请通过id或者fields属性补全！");
        Field f=getField(id);
        if(f==null) f=new Field();
        f.setField(map);
//        if(fieldKey==null) fieldKey="";
//        if(!"".equals(fieldKey)) fieldKey=fieldKey+",";
//        fieldKey=fieldKey+f.getField();
        setField(id, f);
    }

    public Field getField(String id) throws Exception {
        Integer index=fieldmap.getInteger(id);
        if(index==null) return null;
        return fields.get(index);
    }

    public JSONObject getField_J(String id) throws Exception {
        Integer index=fieldmap.getInteger(id);
        if(index==null) return null;
        return flist.get(index);
    }

    private void setField(String id, Field f) throws Exception {
        Integer index=fieldmap.getInteger(id);
        if(index==null) {
            fieldmap.put(id, fields.size());
            fields.add(f);
        }
        else fields.set(index, f);
    }

    public String getId() {
        return id;
    }

    public String getName() {
        if(name==null) name=fieldKeyName;
        return name;
    }

    public String getFieldKeyName() {
        return fieldKeyName;
    }

    public ArrayList<Field> getFields() {
        return fields;
    }

    public boolean isCache() {
        return cache;
    }

    public JSONArray getFieldlist() throws Exception {
        boolean bdatabase=false;
        if(id==null){
            bdatabase=getfromDatabase();
        }
        if(id!=null){
            Dimension d=getDimension(id, session);
            if(d==null){
                setDimensionMap(id, fieldKeyName, fieldKey, session);
            }
            copyDimension(getDimension(id, session));
        }
        return getFieldlist_ini(bdatabase);
    }

    public JSONArray getFieldlist_ini(boolean bdatabase) throws Exception {
        if(flist==null || flist.size()==0){
            String theme="";
            if(session.getTheme()!=null) theme=session.getTheme()+".";
            flist=new JSONArray();
            int len=fields.size();
            for(int i=0; i<len; i++){
                Field f=fields.get(i);
                String fid=f.getId();
                String fname=f.getName();
                String field=f.getField();
                String s=theme+fid;
                JSONObject m= sysCondition.getDimensionField(s);
                if(m==null) throw new Exception("维度字段id["+fid+"]配置不存在，请检查配置文件！");
                if(fname==null) fname=m.getString("comment");
                if(fname==null) fname=field;
                int pos=fname.indexOf(",");
                if(pos>=0) fname=fname.substring(0, pos);
                JSONObject dmap=new JSONObject(m);
                dmap.put("id", field);
                dmap.put("comment", fname);
                dmap.put("notNull", "true");
                dmap.put("isKey", "true");
                String table=m.getString("table");
                if(dmap.get("foreignTab")==null && table!=null){
                    dmap.put("foreignTab", table);
                }
                if(dmap.get("foreignTab")!=null){  //table!=null &&
                    dmap.put("foreignKey", m.getString("field"));
                }
                JSONObject o=new JSONObject();
                o.put("nameField", m.getString("nameField"));
                if(m.get("copyField")!=null) o.put("field", m.getString("copyField"));
                else o.put("field", m.getString("field"));
                dmap.put("from", o);
                flist.add(dmap);
                fielddir.put(field,"1");
                if(!bdatabase){
                    if(fieldKeyName==null){
                        fieldKeyName="";
                    }
                    if(!"".equals(fieldKeyName)) fieldKeyName=fieldKeyName+"/";
                    fieldKeyName=fieldKeyName+fname;
                }
            }
            if(!bdatabase) writeDimensionToDatabase();
        }
        return flist;
    }

    private boolean getfromDatabase() throws Exception {
        String f="";
        int len=fields.size();
        for(int i=0; i<len; i++){
            String fid=fields.get(i).getId();
            f=f+" AND INSTR(','||FIELD||',',',"+fid+",')>0 ";
        }
        String sql="<rule from=\"EXE_DIMENSION\" autoCompletion=\"0\" />" +
                "SELECT ID,NAME,FIELD FROM EXE_DIMENSION WHERE 1=1\n" +f+" AND NVL(STR_COUNT(FIELD,','),0)="+len+"-1 ORDER BY ID ";
        JSONObject p=new JSONObject();
        p.put("printSql","false");
        session.getForResultSet().sql(sql,p, new QueryCallBackHandler(){
            @Override
            public void getData(SqlResultSet rs, JSONArray rslist) throws Exception {
                if(rs.next()){
                    id=rs.getString("ID");
                    fieldKey=rs.getString("FIELD");
                    fieldKeyName=rs.getString("NAME");
                }
            }
        });
        if(id!=null) return true;
        return false;
    }

    public void writeDimensionToDatabase() throws Exception {
        JSONObject m=new JSONObject();
        m.put("NAME",getName());
        fieldKey=fieldKey.replace(" ","");
        m.put("FIELD", fieldKey);
        m.put("CREATE_DATE","SYSDATE");
        m.put("LAST_UPDATED_STAMP","SYSDATE");
        id= DBPub.getIdKeyStr(session, "EXE_DIMENSION");
        m.put("ID", id);
        session.getForUpdate().insertTable("EXE_DIMENSION", m);
    }

    public boolean isDim(String field){
        boolean flag=true;
        int len=fields.size();
        for(int i=0; i<len; i++){
            String f=fields.get(i).getField();
            if((","+field+",").indexOf(","+f+",")<0) {
                flag=false;
                break;
            }
        }
        return flag;
    }

    public String getFieldKey() {
        return fieldKey;
    }

    public SqlSession getSession() {
        return session;
    }

    public JSONObject getFielddir() {
        return fielddir;
    }

    public String getMaster() {
        return master;
    }

    public boolean isStop() {
        return stop;
    }

    public void setStop(boolean stop) {
        this.stop = stop;
    }

    public boolean isIsmap() {
        return ismap;
    }

    public String getFromTab() {
        return fromTab;
    }

    public void setIsmap(boolean ismap) {
        this.ismap = ismap;
    }

    public void setFromTab(String fromTab) {
        this.fromTab = fromTab;
    }

    public void setSession(SqlSession session) {
        this.session = session;
    }
}
